#ifndef K_AUTO_PTR_H
#define K_AUTO_PTR_H
#pragma once

#include "KGlobal.h"
#include "KNoCopy.h"

template <class T, bool IsArray = false>
class KAutoPtr : KNoCopy {
public:
    KAutoPtr() : m_ptr(nullptr) {}
    explicit KAutoPtr(T *ptr) : m_ptr(KVerify(ptr)) {}
    ~KAutoPtr()                             { reset(); }
public:
    T *operator->() const                   { return get(); }
    T &operator*() const                    { return *get(); }
    T &operator[](std::ptrdiff_t i) const   { return get()[i]; }
    operator T *() const                    { return get(); }
public:
    T *get() const                          { return m_ptr; }
    T *release()                            { return exchange(nullptr); }
    void reset()                            { destroy(release()); }
    void reset(T *ptr)                      { destroy(exchange(KVerify(ptr))); }
private:
    static void destroy(T *ptr);
    T *exchange(T *ptr);
private:
    T *m_ptr;
};

template <class T, bool IsArray>
inline void KAutoPtr<T, IsArray>::destroy(T *ptr)
{
    if (IsArray) {
        delete[] ptr;
    } else {
        delete ptr;
    }
}

template <class T, bool IsArray>
inline T *KAutoPtr<T, IsArray>::exchange(T *ptr)
{
    T *old = m_ptr;
    m_ptr = ptr;
    return old;
}

#endif // K_AUTO_PTR_H